#ifndef CPU_H
#define CPU_H

#include "comm/types.h"

//G标志位,指示段界限的粒度,为0是表示字节为单位,为1时表示4kb为单位,段界限共20位
//因此为0时段大小为1MB,为1时段大小为4GB
#define  SEG_G (1<<15)      
//D/B标志位,为0时操作数和偏移地址为16位,为1时为32位(该位是为了兼容16位包含模式的程序)
#define  SEG_D (1<<14)
//该段存在于内存则为1
#define SEG_P_PRESENT   (1<<7)

//特权级别
#define SEG_DPL0 (0<<5)
#define SEG_DPL3 (3<<5)

#define SEG_CPL0  (0<<0)
#define SEG_CPL3  (3<<0)

//段类型,0是系统段,1是代码段或数据段
#define SEG_S_SYSTEM (0<<4)
#define SEG_S_NORMAL (1<<4)

//段的读写属性类型
#define SEG_TYPE_CODE (1<<3)
#define SEG_TYPE_DATA (0<<3)
#define SEG_TYPE_TSS   (9<<0)

#define SEG_TYPE_RW (1<<1)

#define GATE_TYPE_IDT		(0xE << 8)
#define GATE_TYPE_SYSCALL   (0xC << 8)
#define GATE_P_PRESENT  (1<<15)
#define GATE_DPL0   (0<<13)
#define GATE_DPL3   (3<<13)


#define EFLAGS_DEFAULT  (1<<1)
#define EFLAGS_IF       (1<<9)

#pragma pack(1)
//gdt表中的全局段描述符
typedef struct _segment_desc_t{
    uint16_t limit15_0;
    uint16_t base15_0;
    uint8_t base23_16;
    uint16_t attr;
    uint8_t base31_24;
}segment_desc_t;

//idt表中的中断描述符
typedef struct _gate_desc_t
{
    uint16_t offset15_0;
    uint16_t selector;
    uint16_t attr;
    uint16_t offset31_16;
}gate_desc_t;

//tss段
typedef struct _tss_t 
{
    uint32_t pre_link;
    uint32_t esp0,ss0,esp1,ss1,esp2,ss2;
    uint32_t cr3;
    uint32_t eip,eflags,eax,ecx,edx,ebx,esp,ebp,esi,edi;
    uint32_t es,cs,ss,ds,fs,gs;
    uint32_t ldt;
    uint32_t iomap;
}tss_t;


#pragma pack()



void cpu_init();
void segment_desc_set(int selector,uint32_t base,uint32_t limit,uint16_t attr);
void gate_desc_set(gate_desc_t* desc,uint16_t selector,uint32_t offset,uint16_t attr);
int gdt_alloc_desc();
void gdt_free_seg(int tss_seg);
void switch_to_tss(int tss_seg);
#endif